import datetime
import json
from django.shortcuts import render, redirect, HttpResponse
from web import models
from django_redis import get_redis_connection
from utils.md5 import str_add_uid
from utils.alipay import AliPay
from django.conf import settings
from utils.pagination import Pagination
from django.http import JsonResponse

def price(request):
    # 获取价格非免费版的列表
    price_policy_list = models.PricePolicy.objects.filter(category=2)

    return render(request, 'price.html', {'price_policy_list': price_policy_list})


# 订单展示
def price_payment(request, policy_id):
    policy_obj = models.PricePolicy.objects.filter(id=policy_id).first()
    if not policy_obj:
        return redirect('price')
    # 1.判断number是否合法 为数字
    number = request.GET.get('number', '')  # 获取用户需购买的数量
    if not number or not number.isdecimal():
        return redirect('price')
    number = int(number)
    if number < 1:
        return redirect('price')

    # 2.原支付价格
    origin_price = number * policy_obj.price

    # 3.用户如果之前购买过套餐，升级套餐
    _object = None  # 交易记录对象初始化
    balance = 0  # 之前套餐没过期，剩余期限抵扣的钱
    if request.tracer.price_policy.category == 2:
        _object = models.Transaction.objects.filter(user=request.tracer.user, status=2).order_by('-id').first()
        # 原套餐总时间
        raw_total_time = _object.end_datetime - _object.start_datetime
        # 套餐剩余时间
        balance_time = _object.end_datetime - datetime.datetime.now()
        # 套餐剩余抵扣价格 = 套餐总价格 / 总时间 * 套餐剩余时间 （按天计算）
        if raw_total_time == balance_time:
            balance = _object.price_policy.price * _object.count / raw_total_time.days * (balance_time.days - 1)
        else:
            balance = _object.price_policy.price * _object.count / raw_total_time.days * balance_time.days

    if balance >= origin_price:
        return redirect('price')
    context = {
        'policy_id': policy_id,
        'number': number,
        'balance': round(balance, 2),  # 抵扣金额，保留两位小数
        'pay_price': origin_price - round(balance, 2),  # 实际支付价格
        'origin_price': origin_price,  # 原价
    }

    # 将数据写入redis
    key = "payment_%s" % request.tracer.user.mobile_phone
    conn = get_redis_connection()
    conn.set(key, json.dumps(context), ex=60 * 30)  # 设置超时时间 30分钟

    context['policy_obj'] = policy_obj
    context['transaction_obj'] = _object  # 原交易记录
    return render(request, 'price_payment.html', context)


# 创建订单，写入数据库
def pay(request):
    # 获取redis的数据，创建交易记录，写入数据库,去支付宝支付
    conn = get_redis_connection()
    key = 'payment_%s' % request.tracer.user.mobile_phone
    conn_string = conn.get(key)
    # 如果不存在，则订单超时
    if not conn_string:
        return redirect('price')
    context = json.loads(conn_string.decode('utf-8'))
    # 根据数据，创建交易记录(未支付)状态，如果已支付，则更新status =2
    # 生成订单号
    order = str_add_uid(request.tracer.user.mobile_phone)
    models.Transaction.objects.create(
        order=order,
        status=1,
        user=request.tracer.user,
        price_policy_id=context['policy_id'],
        count=context['number'],
        price=context['pay_price'],
    )

    # 2. 跳转到支付去支付
    #    - 根据申请的支付的信息 + 支付宝的文档 => 跳转链接
    #    - 生成一个支付的链接
    #    - 跳转到这个链接
    # 构造字典

    # 未封装方式
    """
    params = {
        'app_id': "2021000118609188",
        'method': 'alipay.trade.page.pay',
        'format': 'JSON',
        'return_url': "http://127.0.0.1:8001/pay/notify/",
        'notify_url': "http://127.0.0.1:8001/pay/notify/",
        'charset': 'utf-8',
        'sign_type': 'RSA2',
        'timestamp': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        'version': '1.0',
        'biz_content': json.dumps({
            'out_trade_no': order,  # 订单号
            'product_code': 'FAST_INSTANT_TRADE_PAY',
            'total_amount': context['pay_price'],  # 订单价格
            # 订单标题
            'subject': "tracer %s" % models.PricePolicy.objects.filter(id=context['policy_id']).first().title
        }, separators=(',', ':'))
    }

    # 获取待签名的字符串
    unsigned_string = "&".join(["{0}={1}".format(k, params[k]) for k in sorted(params)])

    # 签名 SHA256WithRSA(对应sign_type为RSA2)
    from Crypto.PublicKey import RSA
    from Crypto.Signature import PKCS1_v1_5
    from Crypto.Hash import SHA256
    from base64 import decodebytes, encodebytes

    # SHA256WithRSA + 应用私钥 对待签名的字符串 进行签名
    private_key = RSA.importKey(open("files/应用私钥_RSA2_PKCS1.txt").read())
    signer = PKCS1_v1_5.new(private_key)
    signature = signer.sign(SHA256.new(unsigned_string.encode('utf-8')))

    # 对签名之后的执行进行base64 编码，转换为字符串
    sign_string = encodebytes(signature).decode("utf8").replace('\n', '')

    # 把生成的签名赋值给sign参数，拼接到请求参数中。

    from urllib.parse import quote_plus
    result = "&".join(["{0}={1}".format(k, quote_plus(params[k])) for k in sorted(params)])
    result = result + "&sign=" + quote_plus(sign_string)

    gateway = "https://openapi.alipaydev.com/gateway.do"
    ali_pay_url = "{}?{}".format(gateway, result)

    return redirect(ali_pay_url)
    """

    # 封装后的方式
    ali_pay = AliPay(
        appid=settings.ALI_APPID,
        app_notify_url=settings.ALI_NOTIFY_URL,
        return_url=settings.ALI_RETURN_URL,
        app_private_key_path=settings.ALI_PRI_KEY_PATH,
        alipay_public_key_path=settings.ALI_PUB_KEY_PATH
    )
    query_params = ali_pay.direct_pay(
        subject="tracer %s" % models.PricePolicy.objects.filter(id=context['policy_id']).first().title,  # 商品简单描述
        out_trade_no=order,  # 商户订单号
        total_amount=context['pay_price']
    )
    pay_url = "{}?{}".format(settings.ALI_GATEWAY, query_params)
    return redirect(pay_url)

def pay_notify(request):
    """ 支付成功之后触发的URL """
    ali_pay = AliPay(
        appid=settings.ALI_APPID,
        app_notify_url=settings.ALI_NOTIFY_URL,
        return_url=settings.ALI_RETURN_URL,
        app_private_key_path=settings.ALI_PRI_KEY_PATH,
        alipay_public_key_path=settings.ALI_PUB_KEY_PATH
    )

    if request.method == 'GET':
        # 只做跳转，判断是否支付成功了，不做订单的状态更新。
        # 支付吧会讲订单号返回：获取订单ID，然后根据订单ID做状态更新 + 认证。
        # 支付宝公钥对支付给我返回的数据request.GET 进行检查，通过则表示这是支付宝返还的接口。
        params = request.GET.dict()
        sign = params.pop('sign', None)
        status = ali_pay.verify(params, sign)
        if status:
            
            current_datetime = datetime.datetime.now()
            out_trade_no = params['out_trade_no']
            _object = models.Transaction.objects.filter(order=out_trade_no).first()

            _object.status = 2
            _object.start_datetime = current_datetime
            _object.end_datetime = current_datetime + datetime.timedelta(days=365 * _object.count)
            _object.save()
            
            return HttpResponse('支付完成')
        return HttpResponse('支付失败')
"""
    else:
        from urllib.parse import parse_qs
        body_str = request.body.decode('utf-8')
        post_data = parse_qs(body_str)
        post_dict = {}
        for k, v in post_data.items():
            post_dict[k] = v[0]

        sign = post_dict.pop('sign', None)
        status = ali_pay.verify(post_dict, sign)
        # 更新订单信息
        if status:
            current_datetime = datetime.datetime.now()
            out_trade_no = post_dict['out_trade_no']
            _object = models.Transaction.objects.filter(order=out_trade_no).first()

            _object.status = 2
            _object.start_datetime = current_datetime
            _object.end_datetime = current_datetime + datetime.timedelta(days=365 * _object.count)
            _object.save()
            return HttpResponse('success')

        return HttpResponse('error')

"""


# 订单列表
def order_list(request):
    # 获取除免费套餐下该用户所有订单信息
    queryset = models.Transaction.objects.filter(user=request.tracer.user, price_policy__category=2).all()

    # 调用自定义的分页类
    page_object = Pagination(
        current_page=request.GET.get('page'),
        all_count=queryset.count(),
        base_url=request.path_info,
        query_params=request.GET,
        per_page=8,  # 每页显示数据条数
    )
    order_obj_list = queryset[page_object.start:page_object.end]
    return render(request, 'order_list.html', {'order_list': order_obj_list,
                                               'page_html': page_object.page_html()
                                               })


# 我的订单 未支付 订单立即支付
def pay_now(request, transaction_id):
    transaction_obj = models.Transaction.objects.filter(id=transaction_id).first()
    if not transaction_obj:
        return redirect('order_list')
    order = transaction_obj.order
    policy_id = transaction_obj.price_policy_id
    price = transaction_obj.price
    ali_pay = AliPay(
        appid=settings.ALI_APPID,
        app_notify_url=settings.ALI_NOTIFY_URL,
        return_url=settings.ALI_RETURN_URL,
        app_private_key_path=settings.ALI_PRI_KEY_PATH,
        alipay_public_key_path=settings.ALI_PUB_KEY_PATH
    )
    query_params = ali_pay.direct_pay(
        subject="tracer %s" % models.PricePolicy.objects.filter(id=policy_id).first().title,  # 商品简单描述
        out_trade_no=order,  # 商户订单号
        total_amount=price
    )
    pay_url = "{}?{}".format(settings.ALI_GATEWAY, query_params)
    return redirect(pay_url)


# 取消订单
def cancel_order(request):
    transaction_id = request.GET.get('oid','')
    print(transaction_id)
    transaction_obj=models.Transaction.objects.filter(id=transaction_id).first()
    if not transaction_obj:
        return redirect('order_list')
    transaction_obj.delete()
    return JsonResponse({'status': True})


